<template>
  <div>
    <label v-if="label" :class="{ 'i-form-item-label-required': isRequired }">{{ label }}</label>
    <div>
      <slot></slot>
      <div v-if="validateState === 'error'" class="i-form-item-message">{{ validateMessage }}</div>
    </div>
  </div>
</template>

<script>
/**
 * 需要预先将 FormItem 的每个实例缓存在 Form 中
 * 当每个 FormItem 渲染时，将其自身（this）作为参数通过 dispatch 派发到 Form 组件中，
 * 然后通过一个数组缓存起来；同理当 FormItem 销毁时，将其从 Form 缓存的数组中移除
 */
import emitter from "@mixins/emitter";
import AsyncValidator from "async-validator";
export default {
  name: "iFormItem",
  inject: ["form"], //要拿到 Form 中 model 里的数据，使用通信方法 provide / inject
  mixins: [emitter],
  props: {
    label: {
      type: String,
      default: ""
    },
    prop: {
      type: String
    }
  },
  data() {
    return {
      isRequired: false, // 是否为必填
      validateState: "", // 校验状态
      validateMessage: "" // 校验不通过时的提示信息
    };
  },
  computed: {
    // 从 Form 的 model 中动态得到当前表单组件的数据
    fieldValue() {
      return this.form.model[this.prop];
    }
  },
  methods: {
    setRules() {
      let rules = this.getRules();
      if (rules.length) {
        rules.every(rule => {
          // 如果当前校验规则中有必填项，则标记出来
          this.isRequired = rule.required;
        });
      }
      this.$on("on-form-blur", this.onFiledBlur);
      this.$on("on-form-change", this.onFiledChange);
    },

    /**
     * 从form的rules属性中，获取当前formItem的校验规则
     */
    getRules() {
      let formRules = this.form.rules;
      formRules = formRules ? formRules[this.prop] : [];
      return [].concat(formRules || []);
    },

    /**
     * 只支持 blur 和 change，所以过滤出符合要求的 rule 规则
     */
    getFilterRule(trigger) {
      const rules = this.getRules();
      return rules.filter(
        //rule => !rule.trigger || rule.trigger.indexOf(trigger) !== -1
        rule => {
          console.log(rule, "rule");
          rule.trigger && rule.trigger.includes(trigger);
        }
      );
    },

    /**
     * 校验数据
     */
    validate(trigger, callback = function() {}) {
      let rules = this.getFilterRule(trigger);
      if (!rules || rules.length === 0) {
        return true;
      }

      // 设置状态为校验中
      this.validateState = "validating";

      // 以下为 async-validator 库的调用方法
      let descriptor = {};
      descriptor[this.prop] = rules;

      const validator = new AsyncValidator(descriptor);
      let model = {};

      model[this.prop] = this.fieldValue; //从 Form 的 model 中动态得到当前表单组件的数据

      validator.validate(model, { firstFields: true }, errors => {
        this.validateState = !errors ? "success" : "error";
        this.validateMessage = errors ? errors[0].message : "";

        callback(this.validateMessage);
      });
    },
    onFiledBlur() {
      // 来自Input的派发事件 this.dispatch("iFormItem", "on-form-blur", this);
      this.validate("blur");
    },
    onFiledChange(value) {
      this.validate("change");
    },
    // 重置数据
    resetField() {
      this.validateState = "";
      this.validateMessage = "";
      this.form.model[this.prop] = this.initialValue;
    }
  },
  mounted() {
    console.log("formItem中的mounted");
    // 如果没有传入 prop，则无需校验，也就无需缓存
    if (this.prop) {
      this.dispatch("iForm", "on-form-item-add", this);

      // 设置初始值，以便在重置时恢复默认值
      this.initialValue = this.fieldValue; //从 Form 的 model 中动态得到当前表单组件的数据
      this.setRules();
    }
  },
  destroyed() {
    this.dispatch("iForm", "on-form-item-remove", this);
  }
};
</script>

<style>
.i-form-item-label-required:before {
  content: "*";
  color: red;
}
.i-form-item-message {
  color: red;
}
</style>
